"""
The world class is responsible for handling objects in a centralized location.
"""
from command import factory
from zone import zone
from room import room
import player
from entity import entity
import shlex
import os
from os import path
from cPickle import load, dump

class World(object):
    startRoom = None
    picklevars = ['startRoom']

    __instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = World.load()
        if not cls.__instance:
            cls.__instance = super(World, cls).__new__(cls, *args, **kwargs)
        cls.__instance.initialize()
        cls.__instance.loadZones()
        return cls.__instance
        
    def initialize(self):
        #banner
        input = open("data/banner")
        self.banner = input.readlines()
        input.close()
        self.players = []
        self.generics = {}
        self.objects = {}
        self.rooms = {}
        self.zones = []

    def save(self):
        output = open('data/mud.dat', 'w')
        dump(self, output)
        output.close()

    @staticmethod
    def load():
        if path.exists("data/mud.dat"):
            input = open("data/mud.dat", "r")
            obj = load(input)
            input.close()
            return obj
        else:
            return None

    def buildRoom(self, zone):
        """
        We create a room, add the component and add the room to the zone if a zone was specified.
        """
        obj = entity()
        obj.attachComponent('room')
        self.addRoom(obj)
        if zone:
            zone.rooms.append(obj)
        return obj
    
    def loadZones(self):
        for fl in os.listdir("data/zones"):
            if not fl.endswith(".zon"):
                continue
            zoneobj = zone.deserialize(path.join("data/zones", fl))
            for room in zoneobj.rooms: #add all the rooms to the room mapping
                self.rooms[room.uid] = room
            self.zones.append(zoneobj)
        if not self.zones:
            #we need to create a zone, then creat a room to go in it for our start room.
            zoneobj = zone()
            self.zones.append(zoneobj)
            zoneobj.name = "Start"
            roomobj = self.buildRoom(zoneobj)
            self.startRoom = roomobj

    def __getstate__(self):
        ret = {}
        for var in self.picklevars:
            if self.__dict__.has_key(var):
                ret[var] = self.__dict__[var]
        return ret

    def addRoom(self, obj):
        self.rooms[obj.uid] = obj

    def handleCommand(self, player, line):
        line = line.strip()
        if not len(line):
            return

        args = shlex.split(line)
        command = args[0]
        args = args[1:]
        if not factory._registry.has_key(command):
            player.client.writeline("huh?")
            return

        factory._registry[command].execute(player, command, args)

    def shutdown(self):
        self.save()
        for zoneobj in self.zones:
            zoneobj.serialize()
        for pc in self.players:
            player.save(pc)
            player.message(pc, "Shutting down...")
        self.running = False

    def schedule(self):
        pass

world = World()